package com.icode.dao.impl;

import com.icode.core.model.AbstractEntity;
import com.icode.dao.EntityDao;
import org.hibernate.ObjectNotFoundException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import java.util.Arrays;
import java.util.List;

/**
 * Created with IntelliJ IDEA.
 * User: ZhongGang
 * Date: 13-6-23
 * Time: 上午1:32
 */
@Repository("entityDao")
public class EntityDaoImpl implements EntityDao {

    @Autowired
    protected SessionFactory sessionFactory;


    @Override
    public Session currentSession() {
        return sessionFactory.getCurrentSession();
    }

    @Override
    public <T extends AbstractEntity> void saveOrUpdate(T t) {
        currentSession().saveOrUpdate(t);
    }

    @Override
    public <T extends AbstractEntity> void saveOrUpdate(List<T> t) {
        Session currentSession = currentSession();
        for (T t1 : t) {
            currentSession.saveOrUpdate(t1);
        }
    }

    @Override
    public <T extends AbstractEntity> List<T> findAll(Class<T> t) {
        String hql = "from " + t.getName();
        Query query = currentSession().createQuery(hql);
        return query.list();
    }

    @Override
    public <T extends AbstractEntity> List<T> findAll(Class<T> t, boolean active) {
        String hql = "from " + t.getName() + " e where e.active = :active";
        Query query = currentSession().createQuery(hql);
        query.setParameter("active", active);
        return query.list();
    }

    @Override
    public <T extends AbstractEntity> List<T> findActiveEntities(Class<T> t) {
        return findAll(t, true);
    }

    @Override
    public <T extends AbstractEntity> List<T> findDeactiveEntities(Class<T> t) {
        return findAll(t, false);
    }

    @Override
    public <T extends AbstractEntity> void deactive(String guid, Class<T> clazz) {
        String hql = "update " + clazz.getName() + " e set e.active = false where e.guid = :guid";
        Query query = currentSession().createQuery(hql);
        query.setParameter("guid", guid);
        query.executeUpdate();
    }

    @Override
    public <T extends AbstractEntity> void active(String guid, Class<T> clazz) {
        String hql = "update " + clazz.getName() + " e set e.active = true where e.guid = :guid";
        Query query = currentSession().createQuery(hql);
        query.setParameter("guid", guid);
        query.executeUpdate();
    }

    @Override
    public <T extends AbstractEntity> void delete(String guid, Class<T> clazz) {
        String hql = "delete from " + clazz.getName() + " e where e.guid = :guid";
        Query query = currentSession().createQuery(hql);
        query.setParameter("guid", guid);
        query.executeUpdate();
    }

    @Override
    public <T extends AbstractEntity> T findByGuid(Class<T> clazz, String guid) {
        String hql = "from " + clazz.getName() + " e where e.guid = :guid";
        Query query = currentSession().createQuery(hql);
        query.setParameter("guid", guid);
        List<T> results = query.list();
        if (results.isEmpty()) {
        throw new ObjectNotFoundException(guid, clazz.getName());
    }
        return results.get(0);
    }

    @Override
    public <T extends AbstractEntity> List<T> findByGuids(Class<T> clazz, List<String> guids) {
        String hql = "from " + clazz.getName() + " e where e.guid in(:guids)";
        Query query = currentSession().createQuery(hql);
        query.setParameterList("guids", guids);
        return query.list();
    }

    @Override
    public <T extends AbstractEntity> List<T> findByGuids(String[] guids, Class<T> clazz) {
        List<String> guidList = Arrays.asList(guids);
        return findByGuids(clazz, guidList);
    }

    @Override
    public <T extends AbstractEntity> List<T> findByGuids(Class<T> clazz, String... guids) {
        List<String> guidList = Arrays.asList(guids);
        return findByGuids(clazz, guidList);
    }
}
